/* 
 * Copyright (C) 2006 Sasa Coh <sasacoh@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using UIFramework;

namespace MenuDesigner
{
  public partial class Demo : Form
  {
    #region Variables
    
    protected CComponentController control;

    #endregion Variables

    #region Constructor

    public Demo()
    {
      InitializeComponent();

      string str = new string(' ', 255);
      richTextBox1.Lines = new string[] { str, str, str, str, str, str, str };
 
      ///////////////////////////////////////////////////////////////
      control = new CComponentController();

      Renderer renderer = new Renderer(this);
      CTimerFactoryImpl tmrFactory = new CTimerFactoryImpl();

      control.attach(renderer);
      control.setTimerFactory(tmrFactory);

      new EntryPage();
      new InitPage();
      new MenuPage();
      new SelectLanguagePage();
      new ListPage();
      new EditingPage();
      new ItemDetailsPage();
      new AddItemPage();

      control.setActivePage((int)EPages.P_ENTRY);
    }

    #endregion Constructor

    #region Methods

    public void writeText(int xaxis, int yaxis, String text) 
    {
      string[] tempArray = richTextBox1.Lines;
      string line = tempArray[yaxis];
      line = line.Remove(xaxis, text.Length);
      tempArray[yaxis] = line.Insert(xaxis, text);
      richTextBox1.Lines = tempArray;      
    }

    public void setCursor(int xaxis, int yaxis)
    {
      Cursor cur = richTextBox1.Cursor;
      Point pt = new Point(xaxis,yaxis);
//      cur. .HotSpot = pt;
      //richTextBox1.ps
    }

    #endregion Methods

    #region Controller
    
    private void softKey1_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onSoftKey(1);
    }

    private void softKey2_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onSoftKey(3);
    }

    private void softKey3_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onSoftKey(5);
    }

    private void softKey4_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onSoftKey(0);
    }

    private void softKey5_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onSoftKey(2);
    }

    private void softKey6_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onSoftKey(4);
    }

    private void softKey7_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onSoftKey(6);
    }

    private void EscButton_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onEscKey();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_1);
    }

    private void buttonOK_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onOkKey();
    }

    private void button2_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_2);
    }

    private void button3_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_3);
    }

    private void button6_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_6);
    }

    private void button5_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_5);
    }

    private void button4_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_4);
    }

    private void button7_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_7);
    }

    private void button8_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_8);
    }

    private void button9_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_9);
    }

    private void button12_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_star);
    }

    private void button0_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_0);
    }

    private void button10_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDigitKey((int)ENumKeyTags.NumKey_hash);
    }

    private void buttonClear_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onClearKey();
    }

    private void MenuButton_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onMenuKey();
    }
    
    private void buttonLeft_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onLeftKey();
    }

    private void buttonRight_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onRightKey();
    }

    private void buttonUp_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onUpKey();
    }

    private void buttonDown_Click(object sender, EventArgs e)
    {
      control.getAccessIf().onDownKey();
    }

    #endregion Controller

  }

  ///////////////////////////////////////////////////////////////////////////////////////

  #region MenuStructure

  public enum EPages : int
  { 
    P_ENTRY = 0,
    P_INIT,
    P_EDIT,
    P_LIST,
    P_DETAILS,
    P_ADDITEM,
    P_MENU,
    P_LANGUAGES
  }
  ///////////////////////////////////////////////////////////////////////////////////////
  /// <summary>
  /// 
  /// </summary>
  public class EntryPage : CPage
  {
    public EntryPage()
      : base((int)EPages.P_ENTRY)
    {
      this.forgetPage(true);

      CText text = new CText("Hello world!", EAlignment.justify_left);
      this.add(text);

      CText text1 = new CText("Press");
      text1.PosY = 2;
      text1.Align = EAlignment.justify_center;
      this.add(text1);

      CLink link = new CLink("softkey to continue", (int)EPages.P_INIT);
      link.PosY = 3;
      link.LinkKey = link.PosY;
      this.add(link);
    }
  }

  /// <summary>
  /// 
  /// </summary>
  public class InitPage : CPage
  {
    private CText _timedate;

    public InitPage()
      : base((int)EPages.P_INIT)
    {
      _timedate = new CText("");
      _timedate.PosY = 0;
      CTimeoutDecorator timeDecor = new CTimeoutDecorator(_timedate, 1000);
      timeDecor.OnTimeout += new NoParamDelegate(DateTimeHandler);
      this.add(timeDecor);      
      
      CText welcome = new CText("     Welcome to Menu Designer!        ");
      welcome.PosY = 2;
      CHorizontalFlow flowDecor = new CHorizontalFlow(welcome, 23,250);
      this.add(flowDecor);

      CLink link = new CLink("Menu", (int)EPages.P_MENU);
      this.add(link);
      link.PosY = 5;
      link.LinkKey = link.PosY;


      this.Menu += new NoParamDelegate(MenuHandler);
    }

    private bool MenuHandler()
    {
      _controller.showPage((int)EPages.P_MENU);
      return true;
    }

    private bool DateTimeHandler()
    { 
      //System.DateTime.Now.ToString();
      _timedate.Caption = System.DateTime.Now.ToShortDateString() + " " + System.DateTime.Now.ToShortTimeString();
      return true;
    }

  }

  /// <summary>
  /// 
  /// </summary>
  public class MenuPage : CPage
  { 
    public MenuPage()
      : base((int)EPages.P_MENU, "Menu")
    {
      CLink linkEditing = new CLink("Editing", (int)EPages.P_EDIT);
      linkEditing.PosY = 5;
      linkEditing.LinkKey = linkEditing.PosY;
      this.add(linkEditing);

      CLink linkList = new CLink("List", (int)EPages.P_LIST);
      this.add(linkList);
      linkList.PosY = 3;
      linkList.LinkKey = linkList.PosY;

      CLink linklang = new CLink("Languages", (int)EPages.P_LANGUAGES);
      linklang.PosY = 6;
      linklang.Align = EAlignment.justify_right; 
      linklang.LinkKey = linklang.PosY;
      this.add(linklang);

    }
  }

  /// <summary>
  /// 
  /// </summary>
  public class SelectLanguagePage : CPage
  {
    public SelectLanguagePage()
      : base((int)EPages.P_LANGUAGES, "Languages")
    {
      CRadioButtonGroup rbgroup = new CRadioButtonGroup();

      CCheckBox cbEn = new CCheckBox("English");
      cbEn.OnChecked += new NoParamDelegate(EnglishChecked);
      cbEn.PosY = 3;
      cbEn.LinkKey = cbEn.PosY;
      //cbEn.Checked = true;
      rbgroup.add(cbEn);

      CCheckBox cbDe = new CCheckBox("Deutch");
      cbDe.OnChecked += new NoParamDelegate(DeutchChecked);
      cbDe.PosY = 5;
      cbDe.LinkKey = cbDe.PosY;
      rbgroup.add(cbDe);

      this.add(rbgroup);
    }

    public bool EnglishChecked()
    {
      _controller.eraseComponent(this);
      _controller.Language = new CLanguage(TLangCode.EN);
      _controller.drawComponent(this);
      return true;
    }
    public bool DeutchChecked()
    {
      _controller.eraseComponent(this);
      _controller.Language = new CDeLanguage();
      _controller.drawComponent(this);
      return true;
    }
  }

  /// <summary>
  /// 
  /// </summary>
  public class ListPage : CPage
  {
    private CSelectList sellist;

    public ListPage()
      : base((int)EPages.P_LIST,"List...")
    {
      CComponentList list = new CComponentList();

      list.add(new CText("item1"));
      list.add(new CText("item2"));
      list.add(new CText("item3"));
      list.add(new CText("item4"));
      list.add(new CText("item5"));
      list.add(new CText("item6"));
      list.add(new CText("item7"));
      list.add(new CText("item8"));

      list.PosY = 1;

      sellist = new CSelectList(list, 4);

      this.add(sellist);

      CLink linkadd = new CLink("Add", (int)EPages.P_ADDITEM);
      linkadd.PosY = 5;
      linkadd.LinkKey = linkadd.PosY;
      this.add(linkadd);

      CLink linkdel = new CLink("Delete");
      linkdel.Align = EAlignment.justify_right;
      linkdel.PosY = 6;
      linkdel.LinkKey = linkdel.PosY;
      linkdel.Softkey += new UintDelegate(deleteHandler);
      this.add(linkdel);

      // add MENU button handler for details
      this.Menu += new NoParamDelegate(detailsHandler);
    }

    public bool deleteHandler(int id)
    {
      _controller.eraseComponent(this);
      CText item = (CText)sellist.Selected;
      sellist.remove(item);
      _controller.refresh();
      return false;
    }

    public bool detailsHandler()
    {
      CText item = (CText)sellist.Selected;
      if (item != null)
      {
        ItemDetailsPage detpage = (ItemDetailsPage)_controller.getPage((int)EPages.P_DETAILS);
        if (detpage != null)
        {
          detpage.setValue(item.Caption);
          _controller.showPage((int)EPages.P_DETAILS);
        }
      }
      return false;
    }

    public CText getSelected()
    {
      return (CText)sellist.Selected;
    }

    public void addItem(CText item)
    {
      sellist.add(item);
    }
  }

  public class ItemDetailsPage : CPage
  {
    private CText _oldValue;
    private CEditField _newValue;
    private ListPage _partnerPage;

    public ItemDetailsPage() 
      : base((int)EPages.P_DETAILS,"Details")
    {
      _oldValue = new CText("");
      _oldValue.PosY = 3;
      add(_oldValue);
      
      _newValue = new CEditField(">","",true);
      _newValue.PosY = 5;
      _newValue.LinkKey = _newValue.PosY;
      _newValue.Ok += new NoParamDelegate(okHandler);
      add(_newValue);

      _partnerPage = (ListPage)_controller.getPage((int)EPages.P_LIST);
    }

    public void setValue(string value) 
    {
      _oldValue.Caption = value;
      _newValue.Caption = value;
    }

    public string getValue()
    {
      return _newValue.Caption;
    }

    private bool okHandler()
    {
      CText item = (CText)_partnerPage.getSelected();
      item.Caption = _newValue.Caption;
      _controller.showPage(_partnerPage.Id);
      return true;
    }
  }

  public class AddItemPage : CPage
  {
    private CEditField _newValue;
    private ListPage _partnerPage;

    public AddItemPage()
      : base((int)EPages.P_ADDITEM, "Add Item")
    {
      _newValue = new CEditField(">", "", true);
      _newValue.PosY = 3;
      _newValue.Ok += new NoParamDelegate(okHandler);
      add(_newValue);

      _partnerPage = (ListPage)_controller.getPage((int)EPages.P_LIST);
    }

    private bool okHandler()
    {
      _partnerPage.addItem(new CText(_newValue.Caption));

      _controller.showPage(_partnerPage.Id);
      return true;
    }

  }
  /// <summary>
  /// 
  /// </summary>
  public class EditingPage : CPage
  {
    private CEditField _edit;

    public EditingPage()
      : base((int)EPages.P_EDIT, "Editing...")
    {
      _edit = new CEditField("prompt>", "");
      _edit.PosY = 5;
      _edit.LinkKey = _edit.PosY;
      _edit.Ok += new NoParamDelegate(okHandler);
      this.add(_edit);

      CIpAddressEdit ipaddr = new CIpAddressEdit("ip>");
      ipaddr.DefaultFocus = true;
      ipaddr.PosY = 3;
      ipaddr.LinkKey = ipaddr.PosY;
      this.add(ipaddr);
    }

    private bool okHandler()
    {
      // handle _edit.Caption;
      _controller.showPage(0);
      return true;
    }
  }

  #endregion MenuStructure Classes

  #region Internationalization

  public class CDeLanguage : CLanguage
  {
    public CDeLanguage()
      : base(TLangCode.DE)
    {
      this.setDefaultKeyMapping();

      // some translations...
      _langTable.Add("languages", "Sprache");
      _langTable.Add("editing", "Editieren");
      _langTable.Add("back", "Zurueck");
      _langTable.Add("link", "Nachste");
      _langTable.Add("list", "Liste");
      _langTable.Add("hello world!", "Hallo Welt");

    }
  }

  #endregion Internationalization

  #region TimerImplementation
  ///////////////////////////////////////////////////////////////////////////////////////
  /// <summary>
  /// 
  /// </summary>
  public class CTimerFactoryImpl : CTimerFactory
  {
    public CTimerFactoryImpl()
      : base()
    { }

    protected override CComponentTimer createTimer(NoParamDelegate deleg)
    {
      return new CTimerImpl(deleg);
    }
  }

  /// <summary>
  /// 
  /// </summary>
  public class CTimerImpl : CComponentTimer
  {
    NoParamDelegate mdeleg;
    Timer mtimer;

    public CTimerImpl(NoParamDelegate deleg)
      : base()
    {
      mdeleg = deleg;
      mtimer = new Timer();
      mtimer.Tick += new EventHandler(timeout);
    }
    
    public override void startMillis(int timeout)
    {
      mtimer.Interval = timeout;
      mtimer.Start();
    }

    public override void abort()
    {
      mtimer.Stop();
    }

    private void timeout(Object obj, EventArgs args)
    {
      this.abort();
      if (mdeleg != null) mdeleg();
    }
  }

  #endregion TimerImplementation

  #region Rendering

  /// <summary>
  /// 
  /// </summary>
  public class Renderer : CObserver
  {
    protected Demo mform;

    public Renderer(Demo form)
      : base()
    {
      mform = form;
    }

    public void drawText(int positionId, string caption, EAlignment justify)
    {
     	int xaxis = 0;
      // clipping 
      if (positionId > 7) return;

	    switch (justify)
      {
        case EAlignment.justify_right: xaxis = 22 - caption.Length; break;
        case EAlignment.justify_center: xaxis = (22 - caption.Length) / 2; break;
      }
	    this.mform.writeText(xaxis, positionId, caption);
    }

    public void drawText(int posX, int posY, string caption)
    {
      if (posY > 7) return;

      this.mform.writeText(posX, posY, caption);
    }

    public void drawEdit(int positionId, string prompt, string caption, int cursor_position, bool selected, EEditMode mode)
    {
      drawText(positionId, prompt + caption, EAlignment.justify_left);

      if (selected) 
      { 
        switch (mode)
        {
          case EEditMode.alphanum_high:
            drawText(19, 0, "ABC");
           break;
         case EEditMode.alphanum_low:
            drawText(19, 0, "abc");
            break;
          case EEditMode.numeric:
            drawText(19, 0, "123");
            break;
        }
      }
      mform.setCursor(caption.Length + prompt.Length,positionId);
    }

    public void eraseText(int positionId, string caption, EAlignment justify)
    {
      int xaxis = 0;
      if (justify == EAlignment.justify_right) xaxis = 22 - caption.Length;
      //this.mform.eraseText(xaxis, positionId, caption);
      this.mform.writeText(xaxis, positionId, new string(' ', caption.Length));
    }

    public void eraseText(int posX, int posY, string caption)
    {
      this.mform.writeText(posX, posY, new string(' ', caption.Length));
    }

    public void eraseEdit(int positionId, string prompt, string caption, int cursor_position)
    {
      eraseText(positionId, prompt + caption, EAlignment.justify_left);
      eraseText(19,0,"   ");
    }

    public void drawCheckMark(int posX, int posY, bool checkedFlag)
    {
      if (checkedFlag)
        drawText(posX, posY, "o");
      else
        drawText(posX, posY, " ");
    }
    public void eraseCheckMark(int posX, int posY)
    {
      drawText(posX, posY, " ");
    }

    public void drawSelection(int position, int type)
    {
      drawText(0, position, "o");
    }

    public void eraseSelection(int position, int type)
    {
      eraseText(0, position, " ");
    }

    // not implemented
    public void clearScreen()
    {
      // todo!!!
    }

    public void drawLink(int posX, int posY)
    {
    }
    public void eraseLink(int posX, int posY)
    {
    }

    public void drawScroller(int positionId, int scrollposition, int scrollSize)
    {
    }

    public void erasePage(bool menu)
    {
    }

    public void eraseTrackBar(int positionId, string caption, int value, int minValue, int maxValue)
    {
    }

    public void eraseScroller(int positionId, int scrollposition, int scrollSize)
    {
    }
    public void eraseProgressBar(int positionId, string caption, int value, int minValue, int maxValue)
    {
    }

    // advanced drawing interface...
    public void drawChar(int posX, int posY, char index)
    {
    }
    public void eraseChar(int posX, int posY)
    {
    }

    public void drawChar(int posX, int posY, ESymbol symbol)
    {
    }

    public void drawArrow(int posY, int side)
    {
    }
    public void eraseArrow(int posY, int side)
    {
    }

  }
  #endregion Rendering

} // namespace UIFramework
